// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "shell/browser/notifications/ohos/ohos_notification.h"

#include "base/json/json_writer.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_thread_impl.h"
#include "shell/browser/notifications/notification_delegate.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace electron {

namespace {

std::unique_ptr<char[]> ConvertSkBitmapToCharArray(const SkBitmap& bitmap) {
  if (!bitmap.readyToDraw()) {
    return nullptr;
  }
  size_t pixelSize = bitmap.computeByteSize();
  auto pixelData(std::make_unique<char[]>(pixelSize));
  if (!bitmap.getPixels()) {
    return nullptr;
  }
  memcpy(pixelData.get(), bitmap.getPixels(), pixelSize);
  return pixelData;  // 返回 std::unique_ptr<char[]> 对象
}

}  // namespace

void OhosNotification::ConvertOptionsToNotificationRequest(
    const NotificationOptions& options,
    ohos::adapter::NotificationRequest& request) {
  request.notificationId = current_id_;
  request.title = base::UTF16ToUTF8(options.title);
  request.message = base::UTF16ToUTF8(options.msg);
  if (request.message.empty()) {
    // if the message is empty, the message section displays the contents of the
    // header
    request.message = request.title;
  }
  if (base::UTF16ToUTF8(options.timeout_type) == "never") {
    request.requireInteraction = true;
  } else {
    request.requireInteraction = false;
  }
  request.silent = options.silent;

  request.timestamp = timestamp_;

  ohos::adapter::NotificationButton btn;
  btn.buttonIndex = current_id_;
  btn.title = base::UTF16ToUTF8(options.close_button_text);
  request.buttons.push_back(btn);

  request.icon.height = options.icon.height();
  request.icon.width = options.icon.width();
  request.icon.buff = ConvertSkBitmapToCharArray(options.icon);

  request.image.height = options.icon.height();
  request.image.width = options.icon.width();
  request.image.buff = ConvertSkBitmapToCharArray(options.icon);
}

OhosNotification::OhosNotification(NotificationDelegate* delegate,
                                   NotificationPresenter* presenter)
    : Notification(delegate, presenter) {
  current_id_ = ++next_id_;
  timestamp_ = static_cast<int64_t>(base::Time::Now().InSecondsFSinceUnixEpoch() * 1000.0);
  RegisterCallbacks();
}

OhosNotification::~OhosNotification() {}

void OhosNotification::Show(const NotificationOptions& options) {
  ohos::adapter::NotificationRequest request;
  ConvertOptionsToNotificationRequest(options, request);
  ohos::adapter::NotificationAdapter::GetInstance().SendNotification(request);
  if (delegate()) {
    delegate()->NotificationDisplayed();
  }
}

void OhosNotification::Dismiss() {
  ohos::adapter::NotificationAdapter::GetInstance().CloseNotification(
      current_id_);
  if (delegate()) {
    delegate()->NotificationClosed();
  }
}

void OhosNotification::RegisterCallbacks() {
  ohos::adapter::NotificationAdapter::GetInstance().RegisterOnClickCallback(
      current_id_, [&](int current_id) {
        auto task = base::BindOnce(
            [](base::WeakPtr<OhosNotification> ohos_notification_click) {
              if (ohos_notification_click &&
                  ohos_notification_click->delegate()) {
                ohos_notification_click->delegate()->NotificationClick();
              }
            },
            weak_factory_.GetWeakPtr());
        content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                                     std::move(task));
      });

  ohos::adapter::NotificationAdapter::GetInstance().RegisterOnCloseCallback(
      current_id_, [&](int current_id) {
        auto task = base::BindOnce(
            [](base::WeakPtr<OhosNotification> ohos_notification_close) {
              if (ohos_notification_close &&
                  ohos_notification_close->delegate()) {
                ohos_notification_close->delegate()->NotificationClosed();
              }
            },
            weak_factory_.GetWeakPtr());
        content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                                     std::move(task));
      });
}

}  // namespace electron
